#include <ximera/graphics/ogre/light.hpp>
#include <ximera/graphics/ogre/ogre.hpp>

namespace ximera { namespace graphics { namespace ogre
{
    LightType ogreToXimera(Ogre::Light::LightTypes type)
    {
        switch (type)
        {
        case Ogre::Light::LT_POINT:  return LightType::Point;
        case Ogre::Light::LT_DIRECTIONAL:  return LightType::Directional;
        case Ogre::Light::LT_SPOTLIGHT:  return LightType::Spot;
        default: return LightType::Point;
        }
    }

    Ogre::Light::LightTypes ximeraToOgre(LightType type)
    {
        switch (type.value)
        {
        case LightType::Point:  return Ogre::Light::LT_POINT;
        case LightType::Directional:  return Ogre::Light::LT_DIRECTIONAL;
        case LightType::Spot:  return Ogre::Light::LT_SPOTLIGHT;
        default: return Ogre::Light::LT_POINT;
        }
    }

    // -----------------------------------------------------------------------

    Light::Light(Ogre::SceneManager* ogreSceneManager, String const& name)
        : ILight(name),
          _ogreSceneManager(ogreSceneManager)
    {
        XIMERA_ASSERT_DEF(ogreSceneManager);

        try 
        {
            _ogreLight = ogreSceneManager->createLight(string_util::wstr2str(name));
        }
        catch (Ogre::Exception& e)
        {
            XIMERA_THROW_OGRE_EXCEPTION(e);
        }
    }

    Light::~Light()
    {
        _ogreSceneManager->destroyLight(_ogreLight);
    }

    math::Vector3 Light::position() const
    {
        return math::Vector3(_ogreLight->getPosition().ptr());
    }

    void Light::position(math::Vector3 const& pos)
    {
        _ogreLight->setPosition(Ogre::Vector3(pos.array()));
    }

    math::Vector3 Light::direction() const
    {
        return math::Vector3(_ogreLight->getDirection().ptr());
    }

    void Light::direction(math::Vector3 const& dir)
    {
        _ogreLight->setDirection(Ogre::Vector3(dir.array()));
    }

    LightType Light::type() const
    {
        return ogreToXimera(_ogreLight->getType());
    }

    void Light::type(LightType lightType)
    {
        _ogreLight->setType(ximeraToOgre(lightType));
    }

    math::Color Light::diffuseColor() const
    {
        return OGRE_TO_XIMERA_COLOR(_ogreLight->getDiffuseColour());
    }

    void Light::diffuseColor(math::Color const& color)
    {
        _ogreLight->setDiffuseColour(XIMERA_TO_OGRE_COLOR(color));
    }

    math::Color Light::specularColor() const
    {
        return OGRE_TO_XIMERA_COLOR(_ogreLight->getSpecularColour());
    }

    void Light::specularColor(math::Color const& color)
    {
        _ogreLight->setSpecularColour(XIMERA_TO_OGRE_COLOR(color));
    }

    bool Light::enabled() const
    {
        return _ogreLight->getVisible();
    }

    void Light::enabled(bool value)
    {
        _ogreLight->setVisible(value);
    }

    bool Light::castShadows() const
    {
        return _ogreLight->getCastShadows();
    }

    void Light::castShadows(bool value) const
    {
        _ogreLight->setCastShadows(value);
    }
}}}